/*
*********************************************************************************************************
*                                                uC/OS-II
*                                          The Real-Time Kernel
*
*                           (c) Copyright 1992-2003, Jean J. Labrosse, Weston, FL
*                                           All Rights Reserved
*
*                                  uC/OS-II C startup for the TI 6000 DSP.
*
*   Copyright 2003, Validated Software Corporation, Lafayette, CO
*   All Rights Reserved
*
*   Modified by:   Jim Elliott
*   Date:           16-Dec-03
*
*   References:
* File    : OS_CFG.H
* By      : Jean J. Labrosse
*   Description:    Set up the C runtime environment
*                   for the TMS320C6414 port on Code Composer Studio
*
*   Contents:
*              static void _auto_init(const void *cinit)  Perform initialization of C variables.
*              extern void __interrupt c_int00()   C ENVIRONMENT ENTRY POINT
*              _CODE_ACCESS void exit(int status)  NORMAL PROGRAM TERMINATION.
*              _CODE_ACCESS void abort(void)  ABNORMAL PROGRAM TERMINATION.
*
*   Revision History - latest change on top
*
*   $Log: /UC03/Source/6414-DSP/src/Support_6414.c $
* Version : V2.75
*********************************************************************************************************
*/
#include <string.h>
#include <stdlib.h>
#include    "..\CPU_H\c6x.h"  /* Obtain customized version containing definition of timer registers. */

#define OS_TICKS_PER_SEC       1000    /* Set the number of ticks in one second                        */

/* This string's contents set by Visual SourceSafe. The $ signs are essential. */
char *SUPPORT_6414_C = "$Header: /Source/6414-DSP/src/Support_6414.c 11    3/15/04 9:02a $";

/* In a Cantata test, define fake timer "registers". */
#ifdef CANTATA
volatile unsigned int TIMER_1_BASE[ 3 ];   /* Use 3 CONSECUTIVE ints instead of special memory address. */
#endif

/* This is required by some library functions used by Cantata. */
void _DATA_ACCESS ( *_cleanup_ptr ) ( void ) = NULL;

#define ALIGN_MASK 0x7
#define ALIGN_PTR(ptr) \
   ((unsigned *)(((unsigned)ptr + ALIGN_MASK) & ~ALIGN_MASK))

#define CINIT   ((void*)&__cinit__)

extern int far __cinit__;
int far main( void );


/*****************************************************************************/
/* _AUTO_INIT()   v4.36 - Perform initialization of C variables.            */
/*  Copyright (c) 1993-2003  Texas Instruments Incorporated                  */
/*****************************************************************************/

static void _auto_init( const void *cinit )
{
   const unsigned int * recptr = cinit;
   unsigned int length;

   if ( ( int ) recptr != -1 )
      while ( ( length = *recptr++ ) != 0 )
      {
         char * to = ( void* ) * recptr++;
         char *from = ( void* ) recptr;

         memcpy( to, from, length );

         from += length;
         recptr = ALIGN_PTR( from );
      }

   /* For TI DSP, removed calls to global constructors. */
}


/*****************************************************************************/
/* BOOT.C   v4.36 - Initialize the C60 C runtime environment                */
/* Copyright (c) 1993-2003  Texas Instruments Incorporated                   */
/*****************************************************************************/

/*---------------------------------------------------------------------------*/
/* ALLOCATE THE MEMORY FOR THE SYSTEM STACK.  THIS SECTION WILL BE SIZED     */
/* BY THE LINKER.                                                            */
/*---------------------------------------------------------------------------*/
__asm( "\t.global __STACK_SIZE" );
#pragma DATA_ALIGN   (_stack, 8);
#pragma DATA_SECTION (_stack, ".stack");
char _stack[ 8 ];

/*****************************************************************************/
/* C_INT00() - C ENVIRONMENT ENTRY POINT                                     */
/*****************************************************************************/
void __interrupt c_int00()
{
   int returnValue;

   /*
    * When the processor is reset interrupts are off.  However using
    * the "Restart" command from the debugger does not turn them off.
    * Turn them off to prevent premature entry into the operating system.
    */
   CSR = 0;

   /* Disable individual interrupts.  The low order bit cannot be set 0. */
   IER = 0;

   /* Clear pending interrupts. */
   ICR = 0xFFFFFFFF;

   /*------------------------------------------------------------------------*/
   /* SET UP THE STACK POINTER IN B15.                                       */
   /* THE STACK POINTER POINTS 1 WORD PAST THE TOP OF THE STACK, SO SUBTRACT */
   /* 1 WORD FROM THE SIZE. ALSO THE SP MUST BE ALIGNED ON AN 8-BYTE BOUNDARY*/
   /*------------------------------------------------------------------------*/
   __asm( "\t   MVKL\t\t   __stack + __STACK_SIZE - 4, SP" );
   __asm( "\t   MVKH\t\t   __stack + __STACK_SIZE - 4, SP" );
   __asm( "\t   AND\t\t   ~7,SP,SP" );


   /*------------------------------------------------------------------------*/
   /* SET UP THE GLOBAL PAGE POINTER IN B14.                                 */
   /*------------------------------------------------------------------------*/
   __asm( "\t   MVKL\t\t   $bss,DP" );
   __asm( "\t   MVKH\t\t   $bss,DP" );

   /*------------------------------------------------------------------------*/
   /* SET UP FLOATING POINT REGISTERS FOR C70 ONLY                           */
   /*------------------------------------------------------------------------*/
#ifdef _TMS320C6700

   FADCR = 0;
   FMCR = 0;
#endif

   /*------------------------------------------------------------------------*/
   /* CALL THE AUTOINITIALIZATION ROUTINE.                                   */
   /*------------------------------------------------------------------------*/
   _auto_init( CINIT );

   /*------------------------------------------------------------------------*/
   /* SETUP THE TIMER.                                                       */
   /*------------------------------------------------------------------------*/

   TIMER_1_BASE[ TIMER_CONTROL ] = 0;
   TIMER_1_BASE[ TIMER_PERIOD ] = ( ( CLOCK_PER_SEC / OS_TICKS_PER_SEC ) / 2 );            // set period register
   TIMER_1_BASE[ TIMER_COUNTER ] = 0x0;
   TIMER_1_BASE[ TIMER_CONTROL ] = ( 1 << 4 ) + ( 1 << 8 ) + ( 1 << 9 );	// C/P = clk mode, PWID=2 clk pulses, CLKSRC=CPU/8

   TIMER_1_BASE[ TIMER_CONTROL ] |= 1;    // turns on T1OUT

   TIMER_1_BASE[ TIMER_CONTROL ] |= ( 1 << 6 ) + ( 1 << 7 );	// start timer, GO=1, ~HLD=1

   /* Enable the timer interrupt and NMI.  Global, maskable interrupts remain off. */
   IER = 0x8002;

   /*------------------------------------------------------------------------*/
   /* CALL THE USER'S PROGRAM.                                               */
   /*------------------------------------------------------------------------*/
   returnValue = main();

   /*------------------------------------------------------------------------*/
   /* CALL EXIT.                                                             */
   /*------------------------------------------------------------------------*/
   exit( returnValue );
}
/*****************************************************************************/
/*  EXIT.C v4.36                                                            */
/*  Copyright (c) 1995-2003 Texas Instruments Incorporated                   */
/*****************************************************************************/

/****************************************************************************/
/* EXIT() - NORMAL PROGRAM TERMINATION.                                     */
/****************************************************************************/
_CODE_ACCESS void exit( int status )
{
   /*
    * Removed calls to functions registered with atiexit, calls to global
    * destructors, and open file cleanup.
    */
   abort();
}

/****************************************************************************/
/* ATEXIT - ATTEMPT TO REGISTER A FUNCTION FOR CALLING AT PROGRAM END       */
/****************************************************************************/

/* TI DSP - Not supported. */


/****************************************************************************/
/* ABORT - ABNORMAL PROGRAM TERMINATION.  CURRENTLY JUST HALTS EXECUTION.   */
/****************************************************************************/

_CODE_ACCESS void abort( void )
{
   //*------------------------------------------------------------------
   //* SET C$$EXIT LABEL SO THE DEBUGGER KNOWS WHEN THE C++ PROGRAM HAS  
   //* COMPLETED.  THIS CAN BE REMOVED IF THE DEBUGGER IS NOT USED.      
   //*-------------------------------------------------------------------
   __asm( "        .global C$$EXIT" );
   __asm( "C$$EXIT: nop" );

   for ( ;; )
      ;   //* CURRENTLY, THIS SPINS FOREVER 
}

